#pragma once

#include <muduo/net/TcpServer.h>
#include <muduo/net/EventLoop.h>
#include <muduo/net/Buffer.h>
#include <muduo/base/Timestamp.h>
#include <memory>
#include <iostream>
#include <string>
#include <unordered_map>
#include <fstream>
#include<functional>
namespace Dict
{
    static const std::string default_file_path = "./dict.txt";
    using namespace muduo::net;
    using muduo::Timestamp;
    class DictServer
    {
    private:
        //when the connection status is connected,call this function
        void OnConnection(const TcpConnectionPtr& conn)
        {
            if(conn->connected())
            {
                std::cout<<"连接建立成功!"<<std::endl;
                return;
            }
            std::cout<<"连接关闭!"<<std::endl;
        }
        void OnMessage(const TcpConnectionPtr& conn,Buffer* buff,Timestamp time)
        {
            std::string search_key = buff->retrieveAllAsString();

            auto it = _datas.find(search_key);
            if(it == _datas.end())
            {
                std::cerr<<"找不到对应的翻译结果,search_key = "<<search_key<<std::endl;
                return;
            }
            conn->send(it->second);
        }
    public:
        using ptr = std::shared_ptr<DictServer>;
        DictServer(const std::string &ip,
                   int port,
                   const std::string &filepath = default_file_path)
                   :_server(&_base_loop,InetAddress(ip,port),"DictServer",TcpServer::Option::kNoReusePort)
        {
            //将字典数据源加载进内存中
            std::ifstream in(filepath);
            if(!in.is_open())
            {
                std::cerr<<"open file failed ,filepath = "<<filepath<<std::endl;
                abort();
            }
            std::string line;
            while(std::getline(in,line))
            {
                if(line.empty()) continue;
                size_t pos = line.find(':');
                if(pos == std::string::npos)
                {
                    continue;
                }
                std::string key = line.substr(0,pos);
                std::string val = line.substr(pos+1);
                std::cout<<"key : "<<key<<std::endl;
                std::cout<<"val : "<<val<<std::endl;
                _datas.insert(std::make_pair(key,val));
                std::cout<<"read line done!"<<std::endl;
            }
            _server.setConnectionCallback(std::bind(&DictServer::OnConnection,this,std::placeholders::_1));
            _server.setMessageCallback(std::bind(&DictServer::OnMessage,this,
                                        std::placeholders::_1,
                                        std::placeholders::_2,
                                        std::placeholders::_3));
        }
        //start server
        void run()
        {
             _server.start();
            _base_loop.loop();
        }
    private:
        EventLoop _base_loop;
        TcpServer _server;
        std::unordered_map<std::string, std::string> _datas;
    };
}